"""
决策过程记录器 - 记录所有买卖决策的完整判断过程

用于回测、实盘、模拟盘、监控等场景的决策分析
每只股票按日期生成独立的日志文件
"""

import os
import logging
from typing import Dict, List, Optional, Any, Tuple
from datetime import datetime
from enum import Enum


class CheckResult(Enum):
    """检查结果枚举"""
    PASS = "✓"           # 通过
    FAIL = "✗"           # 不通过
    SKIP = "○"           # 跳过
    FILTERED = "⚠️"      # 触发但被过滤
    EXECUTED = "🟢"      # 已执行


class DecisionLogger:
    """决策日志记录器"""
    
    def __init__(self, log_dir: str = 'backtest_logs'):
        """
        初始化决策日志记录器
        
        Args:
            log_dir: 日志目录
        """
        self.log_dir = log_dir
        self.loggers = {}  # 每只股票一个logger
        self._ensure_log_dir()
    
    def _ensure_log_dir(self):
        """确保日志目录存在"""
        try:
            if not os.path.exists(self.log_dir):
                os.makedirs(self.log_dir)
        except Exception:
            pass
    
    def _get_logger(self, stock_code: str, date: str) -> logging.Logger:
        """
        获取或创建特定股票和日期的logger
        
        Args:
            stock_code: 股票代码
            date: 日期 (YYYYMMDD)
            
        Returns:
            Logger实例
        """
        logger_key = f"{stock_code}_{date}"
        
        if logger_key in self.loggers:
            return self.loggers[logger_key]
        
        # 创建新logger
        logger = logging.getLogger(f'DecisionLogger_{logger_key}')
        logger.setLevel(logging.INFO)
        logger.propagate = False
        
        # 清除已有的handlers
        logger.handlers.clear()
        
        try:
            # 生成文件名: decision_STOCK_YYYYMMDD.log
            log_file = os.path.join(self.log_dir, f'decision_{stock_code}_{date}.log')
            file_handler = logging.FileHandler(log_file, mode='a', encoding='utf-8')
            file_handler.setLevel(logging.INFO)
            
            # 不使用formatter，直接输出原始内容
            file_handler.setFormatter(logging.Formatter('%(message)s'))
            logger.addHandler(file_handler)
            
            self.loggers[logger_key] = logger
            return logger
        except Exception:
            # 如果创建失败，返回一个空logger
            return logging.getLogger('null')
    
    def log_tick_header(self, stock_code: str, stock_name: str, time: str, 
                       current_price: float, position_status: str):
        """
        记录tick头部信息
        
        Args:
            stock_code: 股票代码
            stock_name: 股票名称
            time: 时间 (YYYY-MM-DD HH:MM:SS)
            current_price: 当前价格
            position_status: 持仓状态（空仓/持仓中）
        """
        try:
            date = time.split()[0].replace('-', '')
            logger = self._get_logger(stock_code, date)
            
            logger.info("=" * 80)
            logger.info(f"📅 {time} | {stock_code} {stock_name} | 价格:{current_price:.2f} | {position_status}")
            logger.info("=" * 80)
        except Exception:
            pass
    
    def log_section_start(self, stock_code: str, time: str, section_name: str):
        """
        记录检查段落开始
        
        Args:
            stock_code: 股票代码
            time: 时间
            section_name: 段落名称（如"买入条件检查"）
        """
        try:
            date = time.split()[0].replace('-', '')
            logger = self._get_logger(stock_code, date)
            logger.info(f"\n【{section_name}】")
        except Exception:
            pass
    
    def log_condition_check(self, stock_code: str, time: str, 
                           condition_name: str, result: CheckResult,
                           details: List[Tuple[str, Any, Any, bool]], 
                           reason: str = "",
                           sub_checks: Optional[List[Dict]] = None,
                           execution: Optional[Dict] = None):
        """
        记录条件检查结果
        
        Args:
            stock_code: 股票代码
            time: 时间
            condition_name: 条件名称
            result: 检查结果（PASS/FAIL/FILTERED/EXECUTED等）
            details: 检查详情列表 [(名称, 实际值, 阈值/期望值, 是否通过), ...]
            reason: 结果原因说明
            sub_checks: 子检查结果（如验证器）
            execution: 执行信息（如果已执行）
        """
        try:
            date = time.split()[0].replace('-', '')
            logger = self._get_logger(stock_code, date)
            
            # 条件标题
            result_text = {
                CheckResult.PASS: "✅ 满足",
                CheckResult.FAIL: "❌ 不满足",
                CheckResult.SKIP: "⏭ 跳过",
                CheckResult.FILTERED: "⚠️ 触发但被过滤",
                CheckResult.EXECUTED: "✅ 满足并执行"
            }.get(result, "")
            
            logger.info(f"\n  ┌─ {condition_name} {'─' * (60 - len(condition_name))}")
            logger.info(f"  │ {result_text}")
            
            if reason:
                logger.info(f"  │   说明: {reason}")
            
            # 详细检查项
            for name, actual, expected, passed in details:
                symbol = CheckResult.PASS.value if passed else CheckResult.FAIL.value
                if expected is not None:
                    logger.info(f"  │   {symbol} {name}: {actual} {'≥' if passed else '≱'} {expected}")
                else:
                    logger.info(f"  │   {symbol} {name}: {actual}")
            
            # 子检查（如验证器）
            if sub_checks:
                for sub in sub_checks:
                    logger.info(f"  │   ○ {sub['name']}: {sub['result']}")
                    if 'details' in sub:
                        for detail in sub['details']:
                            logger.info(f"  │     ● {detail}")
            
            # 执行信息
            if execution:
                logger.info(f"  │")
                logger.info(f"  │ 🟢 【执行{execution['action']}】")
                logger.info(f"  │   价格: {execution['price']:.2f}元 | "
                          f"数量: {execution['quantity']}股 | "
                          f"金额: {execution['amount']:.2f}元")
                if 'profit' in execution:
                    logger.info(f"  │   盈亏: {execution['profit']:.2f}元 "
                              f"({execution['profit_pct']:+.2f}%) | "
                              f"持有{execution['hold_days']}天")
            
            logger.info(f"  └{'─' * 76}")
        except Exception as e:
            pass
    
    def log_skip_reason(self, stock_code: str, time: str, reason: str):
        """
        记录跳过原因
        
        Args:
            stock_code: 股票代码
            time: 时间
            reason: 跳过原因
        """
        try:
            date = time.split()[0].replace('-', '')
            logger = self._get_logger(stock_code, date)
            logger.info(f"  ⏭ {reason}")
        except Exception:
            pass
    
    def log_stop_reason(self, stock_code: str, time: str, reason: str):
        """
        记录停止检查原因
        
        Args:
            stock_code: 股票代码
            time: 时间
            reason: 停止原因
        """
        try:
            date = time.split()[0].replace('-', '')
            logger = self._get_logger(stock_code, date)
            logger.info(f"\n⏹ {reason}")
        except Exception:
            pass
    
    def log_blank_line(self, stock_code: str, time: str):
        """
        记录空行
        
        Args:
            stock_code: 股票代码
            time: 时间
        """
        try:
            date = time.split()[0].replace('-', '')
            logger = self._get_logger(stock_code, date)
            logger.info("")
        except Exception:
            pass
    
    def close(self):
        """关闭所有logger的handlers"""
        for logger in self.loggers.values():
            for handler in logger.handlers:
                handler.close()
        self.loggers.clear()


# 全局单例
_global_decision_logger = None


def get_decision_logger() -> DecisionLogger:
    """获取全局决策日志记录器"""
    global _global_decision_logger
    if _global_decision_logger is None:
        _global_decision_logger = DecisionLogger()
    return _global_decision_logger


def close_decision_logger():
    """关闭全局决策日志记录器"""
    global _global_decision_logger
    if _global_decision_logger is not None:
        _global_decision_logger.close()
        _global_decision_logger = None

